package scales.xml.equals
import scales.xml.{PullType, QName, Elem, Attribs, Attributes, Attribute, XmlItem, XmlPath, EndElem, XCC, Misc, Miscs}
import scales.xml.serializers.NamespaceContext
import scala.collection.immutable.{ Stack, Map }
import BasicPaths._
class ComparisonContext private (private val lnc : NamespaceContext = null,
private val rnc : NamespaceContext = null,
val path : BasicPath, private val parent : ComparisonContext = null, val streamPosition : Int = 0) {
def withPosition( newStreamPosition : Int ) =
new ComparisonContext(lnc, rnc, path, parent, newStreamPosition)
def toDifferenceAsStream[T](t : T, filter : Iterator[PullType] => Iterator[PullType] = LogicalFilters.joinTextAndCData(_))(implicit tv : T => StreamComparable[T]) : Stream[PullType] = filter( tv(t).underlyingIterator ).take(streamPosition).toStream
import ComparisonContext.emptyWithDefault
def leftNamespaceContext : Option[NamespaceContext] =
Option(lnc)
def rightNamespaceContext : Option[NamespaceContext] =
Option(rnc)
def startElems( leftElem : Elem, rightElem : Elem ) : ComparisonContext =
new ComparisonContext(
scales.xml.doElement(leftElem,
if (lnc eq null)
emptyWithDefault
else
lnc.mappings)
, scales.xml.doElement(rightElem,
if (rnc eq null)
emptyWithDefault
else
rnc.mappings)
, if (path.isEmpty)
scales.utils.one((leftElem.name, Map[String, Int]()))
else {
val qname = leftElem.name
val (h :: r) = path
val qn = qname.qualifiedName
val count = h._2.get(qn).getOrElse(0)
(qname, Map[String, Int]()) ::
(h._1, h._2.updated(qn, count + 1)) :: r
}
, this)
def pathString : String = {
var str = ""
var l = path
while( ! l.isEmpty ) {
val head :: tail = l
l = tail
val qn = head._1.qualifiedName
val count =
if (tail.isEmpty) 1
else {
val nhead :: rest = tail
nhead._2(qn)
}
str = "/"+ qn + "["+ count +"]" + str
}
str
}
def endElem : ComparisonContext =
if (parent eq null)
error("Cannot call endElem on a root context")
else
new ComparisonContext(parent.lnc, parent.rnc, path.tail, parent.parent)
def parentContext : Option[ComparisonContext] =
Option(parent)
}
object ComparisonContext {
protected[xml] val emptyWithDefault = Map(""->"")
def apply(path : BasicPath) : ComparisonContext =
new ComparisonContext(null, null, path, null)
def apply() : ComparisonContext =
new ComparisonContext(null, null, Nil, null)
val empty = apply()
def unapply( c : ComparisonContext ) : Option[(Option[NamespaceContext], Option[NamespaceContext], BasicPath, Option[ComparisonContext])] =
Some(c.leftNamespaceContext, c.rightNamespaceContext, c.path,
c.parentContext)
}
trait ComparisonContextImplicits {
implicit object BasicPathNames extends scales.xml.xpath.Names[BasicPath] {
def name(implicit t : BasicPath) : Option[scales.xml.QName] =
t.headOption.map( _._1 )
}
implicit object ComparisonContextNames extends scales.xml.xpath.Names[ComparisonContext] {
def name(implicit t : ComparisonContext) : Option[scales.xml.QName] =
t.path.headOption.map( _._1 )
}
}